/*
 * Copyright 2009 Cedric Priscal
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.serialport.sample;

import java.io.IOException;

import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

/**
 * 执行串口回环测试
 * 通过发送数据到串口并验证数据是否被正确地回收到来检测串口通信的可靠性
 */
public class LoopbackActivity extends SerialPortActivity {

    byte mValueToSend;
    boolean mByteReceivedBack;
    // 用于线程同步的对象
    Object mByteReceivedBackSemaphore = new Object();
    Integer mIncoming = new Integer(0);
    Integer mOutgoing = new Integer(0);
    Integer mLost = new Integer(0);
    Integer mCorrupted = new Integer(0);
    // private volatile boolean mIsRunning = true;

    // 执行发送数据的线程
    SendingThread mSendingThread;
    TextView mTextViewOutgoing;
    TextView mTextViewIncoming;
    TextView mTextViewLost;
    TextView mTextViewCorrupted;
    private String TAG = "LoopbackActivity";

    private class SendingThread extends Thread {
        @Override
        public void run() {
            while (!isInterrupted()) {
                synchronized (mByteReceivedBackSemaphore) {
                    mByteReceivedBack = false;
                    try {
                        if (mOutputStream != null) {
                            // Log.e("LoopbackActivity ", "mOutputStream is " + mOutputStream.toString());
                            // 发送当前字节值
                            synchronized (mOutputStream) {
                                mOutputStream.write(mValueToSend);
                                Log.e(TAG, "Sent byte: " + mValueToSend);
                            }
                        } else {
                            return;
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                        return;
                    }
                    mOutgoing++;
                    // Wait for 100ms before sending next byte, or as soon as
                    // the sent byte has been read back.
                    try {
                        // 释放锁
                        Log.e(TAG, "Waiting for byte to be received back");
                        mByteReceivedBackSemaphore.wait(100);
                        if (mByteReceivedBack == true) {
                            // Byte has been received
                            mIncoming++;
                        } else {
                            Log.e(TAG, "Byte not received back, timeout");
                            // Timeout
                            mLost++;
                        }
                        runOnUiThread(new Runnable() {
                            public void run() {
                                mTextViewOutgoing.setText(mOutgoing.toString());
                                mTextViewLost.setText(mLost.toString());
                                mTextViewIncoming.setText(mIncoming.toString());
                                mTextViewCorrupted.setText(mCorrupted.toString());
                            }
                        });
                    } catch (InterruptedException e) {
                    }
                }
                // 增加延时，避免数据发送过快
                /*try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/
            }
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.loopback);
        mTextViewOutgoing = (TextView) findViewById(R.id.TextViewOutgoingValue);
        mTextViewIncoming = (TextView) findViewById(R.id.TextViewIncomingValue);
        mTextViewLost = (TextView) findViewById(R.id.textViewLostValue);
        mTextViewCorrupted = (TextView) findViewById(R.id.textViewCorruptedValue);
        // 确保串口对象不为空
        if (mSerialPort != null) {
            //  创建并启动发送线程
            mSendingThread = new SendingThread();
            mSendingThread.start();
        }
    }

    @Override
    protected void onDataReceived(byte[] buffer, int size) {

        synchronized (mByteReceivedBackSemaphore) {
            int i;
            for (i = 0; i < size; i++) {
                // 遍历接收到的数据，检查是否是预期的字节
                Log.e(TAG, "Received byte: " + buffer[i]);
                if ((buffer[i] == mValueToSend) && (mByteReceivedBack == false)) {
                    Log.e(TAG, "收到的数据和发送数据一致");
                    mValueToSend++;
                    // This byte was expected
                    // Wake-up the sending thread
                    mByteReceivedBack = true;
                    mByteReceivedBackSemaphore.notify();
                } else {
                    // The byte was not expected
                    Log.e(TAG, "收到的数据和发送数据不一致");
                    mCorrupted++;
                }
            }
        }
    }

    @Override
    protected void onDestroy() {
        //mIsRunning = false; // Stop the thread
        if (mSendingThread != null) mSendingThread.interrupt();
        super.onDestroy();
    }
}
